/*******************************************************************************
 * Copyright (c) 2007 Jules White. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: Jules White - initial API and implementation
 ******************************************************************************/
package org.refresh.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.gems.designer.constraints.GemsComplexityContainer;
//import org.gems.designer.constraints.GemsContainerFactory;
//import org.gems.designer.constraints.meta.Property;
//import org.gems.designer.constraints.pojo.ClassMetaType;
//import org.gems.designer.constraints.pojo.JavaDomain;
//import org.gems.designer.constraints.pojo.JavaPackageDomain;
//import org.gems.designer.dsml.deployment.spring.environment.character.DependencyCharacterizer;
//import org.gems.designer.dsml.deployment.spring.environment.character.FeatureFinder;
//import org.gems.designer.dsml.deployment.spring.environment.character.FeaturePropertyProbe;
//import org.gems.designer.dsml.deployment.spring.environment.character.NodeFinder;
//import org.gems.designer.dsml.deployment.spring.environment.character.PostProcessor;
//import org.gems.designer.dsml.deployment.spring.environment.character.PreProcessor;
//import org.gems.designer.dsml.deployment.spring.environment.character.RequirementProbe;
//import org.gems.designer.dsml.deployment.spring.environment.character.ResourceProbe;
//import org.gems.rocs.optimization.goals.FitnessFunction;
//import org.gems.rocs.optimization.goals.FitnessFunctionImpl;
//import org.gems.rocs.optimization.goals.OptimizationUtils;
//import org.gems.rocs.optimization.goals.PropertyTerm;
//import org.gems.rocs.optimization.goals.Term;
//import org.gems.rocs.problems.BinPackingProblemImpl;
//import org.gems.rocs.problems.BinPackingSolution;
//import org.gems.rocs.problems.aspects.VariableDefinition;
//import org.gems.rocs.problems.binpacking.BasicDependencyPredicate;
//import org.gems.rocs.problems.binpacking.Dependency;
//import org.gems.rocs.problems.binpacking.DependencyImpl;
//import org.gems.rocs.problems.binpacking.DependencyPredicate;
//import org.gems.rocs.problems.binpacking.SelectPredicate;
//import org.gems.rocs.solvers.SolutionProvider;

public class RefreshEngine {
	
//	public static final String RESOURCE_REQUIREMENT_TYPE  = "-";
//
//	public static final String PACKED_ITEMS_VARIABLE = "PackedItems";
//
//	public static final String TOTAL_SELECTED_FEATURES_VARIABLE = PACKED_ITEMS_VARIABLE;
//
//	private final Log logger_ = LogFactory.getLog(RefreshEngine.class);
//
//	private List<FeaturePropertyProbe> featurePropertyCharacterizers_ = new LinkedList<FeaturePropertyProbe>();
//
//	private List<DependencyCharacterizer> dependencyCharacterizers_ = new LinkedList<DependencyCharacterizer>();
//
//	private List<RequirementProbe> requirementCharacterizers_ = new LinkedList<RequirementProbe>();
//
//
//	private List features_ = new LinkedList();
//
//	private List targets_ = new LinkedList();
//
//	private List<VariableResolver> variableResolvers_ = new LinkedList<VariableResolver>();
//
//	private List<Dependency> dependencies_ = new LinkedList<Dependency>();
//
//	private Hashtable selectedFeatures_ = new Hashtable();
//
//	private GemsComplexityContainer container_;
//
//	private String fitnessFunction_ = TOTAL_SELECTED_FEATURES_VARIABLE;
//
//	private boolean maximizeFitnessFunction_ = true;
//
//	private SelectionHandler selectionHandler_;
//
//	public RefreshEngine() {
//		init();
//	}
//
//	public void reset() {
//		selectedFeatures_.clear();
//		targets_.clear();
//		features_.clear();
//	}
//
//	public void init() {
//		domain_ = new JavaPackageDomain(Feature.class.getPackage(), Arrays
//				.asList(new Class[] { Feature.class, Node.class }));
//		GemsContainerFactory factory = new GemsContainerFactory();
//		factory.initContainer("container.xml", getClass());
//		GemsComplexityContainer kb2 = (GemsComplexityContainer) factory
//				.createContainer();
//		// kb2.addDomainAdapter(domain_.getDomainAdapte());
//		container_ = kb2;
//	}
//
//	public void selectFeatures() {
//		long ms = System.currentTimeMillis();
//		List<String> userdefinedvars = characterizeApplication(app);
//		characterizeTargetEnvironment();
//
//		// PrologConstraint con = new PrologConstraint("CorrectConfig",
//		// "CorrectConfig",
//		// "The targethost must have the proper configuration",
//		// "configuredProperly(Owner,Value)");
//		// con.setTargetRole("RuntimeContext");
//		// con.setCode("configuredProperly(Owner,Value)");
//		// File lib = new File("prolog/configuration.P");
//		// con.getRequiredLibraries().add(lib);
//		// container_.addConfigurationData(new KeyedConstraintImpl(con,
//		// ClassMetaType.getMetaType(Feature.class), "RuntimeContext"));
//
//		List vitems = new ArrayList(17);
//		for (Object item : itemList_) {
//			if (((Feature) item).getEnabled()) {
//				List valid = validTargets((Feature)item, targets_);//container_.getValidAssignments(item,
//				// "RuntimeContext");
//				if (valid.size() > 0)
//					vitems.add(item);
//				// else
//				// ((Feature) item).setEnabled(false);
//			}
//		}
//
//		for (org.gems.rocs.problems.binpacking.Dependency dep : dependencies_) {
//			Feature dependant = (Feature) dep.getDependentObject();
//			if (dependant.getEnabled()) {
//				for (Object o : dep.getDependencies()) {
//					if (dep.getPredicate() == null)
//						continue;
//					if (dep.getPredicate().getName().equals(
//							BasicDependencyPredicate.REQUIRES.getName())) {
//						if (o == null || !((Feature) o).getEnabled()) {
//							logger_.info("" + dependant
//									+ " is disabled b/c its required feature "
//									+ o + " is disabled");
//							vitems.remove(dependant);
//							dependant.setEnabled(false);
//						}
//					}
//				}
//			}
//		}
//
//		List toremove = new ArrayList();
//		List required = new ArrayList();
//		for (Object o : vitems) {
//			Feature f = (Feature) o;
//			if (!f.getEnabled())
//				toremove.add(f);
//			if(featureConfiguration_ != null){
//				if(featureConfiguration_.selected(f))
//					f.setSelected(true);
//				else if(featureConfiguration_.excluded(f)){
//					f.setEnabled(false);
//					toremove.add(f);
//				}
//			}
//			if (f.isSelected() && f.getEnabled())
//				required.add(f);
//		}
//		for (Object o : toremove) {
//			vitems.remove(o);
//		}
//
//		List<Property> bindims = new ArrayList<Property>(13);
//		List<Property> itemdims = new ArrayList<Property>(13);
//		
//		Hashtable restypes = new Hashtable();
//		for (Object o : vitems) {
//			Feature f = (Feature) o;
//			for(Requirement r : f.getRequirements()){
//				if(RESOURCE_REQUIREMENT_TYPE.equals(r.getRequirementType())){
//					if(restypes.get(r.getTargetProperty()) == null){
//						restypes.put(r.getTargetProperty(), Boolean.TRUE);
//						RequirementTypeEndpoint req = new RequirementTypeEndpoint(r.getTargetProperty(),RESOURCE_REQUIREMENT_TYPE);
//						ResourceEndpoint re = new ResourceEndpoint(r.getTargetProperty());
//						itemdims.add(req);
//						bindims.add(re);
//					}						
//				}
//			}
//		}
//		
//		BinPackingProblemImpl binp = new BinPackingProblemImpl(vitems,
//				targets_, itemdims, bindims);
//
//		binp.setRequiredItems(required);
//		
//		
//		//binp.getSolutionCriteria().clear();
//
//		try {
//			Term t = OptimizationUtils
//					.parseOptimizationCriteria(getFitnessFunction());
//			FitnessFunction fitness = new FitnessFunctionImpl(t,
//					shouldMaximizeFitnessFunction());
//			binp.getSolutionCriteria().add(fitness);
//
//			extractVariables(t, userdefinedvars);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//
//		Hashtable definedv = new Hashtable();
//		List<VariableDefinition> variables = new LinkedList<VariableDefinition>();
//		for (String var : userdefinedvars) {
//			if (definedv.get(var) == null) {
//				definedv.put(var, var);
//				// FeaturePropertyEndpoint ep = new
//				// FeaturePropertyEndpoint(var);
//				// BasicVariableDefinition vd = new
//				// BasicVariableDefinition(items,ep,var);
//				VariableDefinition vd = null;
//				for (VariableResolver vr : getVariableResolvers()) {
//					vd = vr.resolve(var);
//					if (vd != null)
//						variables.add(vd);
//				}
//			}
//		}
//
//		binp.getVariableDefinitions().addAll(variables);
//
//		for (org.gems.rocs.problems.binpacking.Dependency dep : dependencies_) {
//			binp.getDependencies().add(dep);
//		}
//
//		ms = System.currentTimeMillis()-ms;
////		System.out.println("MY setup time:"+ms);
////		System.out.println("Total Items to Pack:"+binp.getItems().size());
//		
//		
//		long start = System.currentTimeMillis();
//		Object sp = container_.processRequest(binp);
////		System.out
////				.println("Total Time:" + (System.currentTimeMillis() - start));
//
//		SolutionProvider sols = (SolutionProvider) sp;
//		BinPackingSolution pack = (BinPackingSolution) sols.nextSolution();
//		
//		if (pack == null)
//			throw new UnsolvableException();
//
//		for (Object key : pack.getHashtable().keySet()) {
//			if (pack.getHashtable().get(key) != null) {
//				logger_.info(key + " selected.");
//				if (selectionHandler_ != null)
//					selectionHandler_.selected(key);
//				
//				selectedFeatures_.put((Feature)key, (Node)pack.getHashtable().get(key)); 
//			} else {
//				if (selectionHandler_ != null)
//					selectionHandler_.notSelected(key);
//			}
//		}
//		/*
//		 * BindingProvider bp = sp.nextSolution();
//		 * 
//		 * long time = System.currentTimeMillis() - start;
//		 * 
//		 * for (RoleBasedObject o : itemList_) { EndPointBindings binds =
//		 * bp.getBindings(assoc, o);
//		 * 
//		 * if (binds != null) { for (Object b : binds) {
//		 * System.out.println("Enabled Feature:" + ((Feature)
//		 * ((JavaRoleBasedObject) o).getObject()) .getId());
//		 * selectedFeatures_.put((Feature) ((JavaRoleBasedObject) o)
//		 * .getObject(), (Node) ((JavaRoleBasedObject) b) .getObject()); } } }
//		 */
//
//	}
//
//	protected void extractVariables(Term t, List<String> vars) {
//		if (t.isLeaf()) {
//			if (t instanceof PropertyTerm) {
//				vars.add(((PropertyTerm) t).getPropertyName());
//			}
//		} else {
//			for (Term c : t.getChildren())
//				extractVariables(c, vars);
//		}
//	}
//
//	public List<org.gems.rocs.problems.binpacking.Dependency> getDependencies() {
//		return dependencies_;
//	}
//
//	public void setDependencies(
//			List<org.gems.rocs.problems.binpacking.Dependency> dependencies) {
//		dependencies_ = dependencies;
//	}
//
//	public List getFeatures() {
//		return features_;
//	}
//
//	public void setFeatures(List features) {
//		features_ = features;
//	}
//
//	public Hashtable getSelectedFeatures() {
//		return selectedFeatures_;
//	}
//
//	public void setSelectedFeatures(Hashtable selectedFeatures) {
//		selectedFeatures_ = selectedFeatures;
//	}
//
//	public List getTargets() {
//		return targets_;
//	}
//
//	public void setTargets(List<Node> targets) {
//		targets_ = targets;
//	}
//
//	protected void addDependency(DependencyImpl d) {
//		dependencies_.add(d);
//	}
//
//	protected Object addFeature(String f) {
//		features_.add(f);
//
//		itemList_.add(f);
//		return f;
//	}
//
//	protected Object addTarget(String n) {
//		targets_.add(n);
//		//container_.add(n, ClassMetaType.getMetaType(Node.class));
//		return n;
//	}
//
//
//
//	public DependencyImpl createDependency(FeatureDependency de) {
//		String pred = de.getPredicate();
//		DependencyPredicate dp = null;
//		StringTokenizer argstr = new StringTokenizer(de.getArguments(), ",",
//				false);
//		if (pred.equalsIgnoreCase(SelectPredicate.NAME)) {
//			dp = new SelectPredicate();
//			String card = argstr.nextToken().trim();
//			if (card.startsWith("[")) {
//				card = card.substring(1, card.length() - 1);
//			}
//			((SelectPredicate) dp).parseCardinality(card);
//		} else if (pred
//				.equalsIgnoreCase(BasicDependencyPredicate.REQUIRES.NAME)) {
//			dp = BasicDependencyPredicate.REQUIRES;
//		} else if (pred
//				.equalsIgnoreCase(BasicDependencyPredicate.EXCLUDES.NAME)) {
//			dp = BasicDependencyPredicate.EXCLUDES;
//		} else if (pred
//				.equalsIgnoreCase(BasicDependencyPredicate.REQUIRED.NAME)) {
//			dp = BasicDependencyPredicate.REQUIRED;
//		}
//
//		if (dp == null)
//			return null;
//
//		LinkedList args = new LinkedList();
//		while (argstr.hasMoreTokens()) {
//			String arg = argstr.nextToken();
//			args.add(getRoleBasedObject(arg));
//		}
//
//		DependencyImpl depo = new DependencyImpl(getRoleBasedObject(de
//				.getFeature()), dp, args);
//		return depo;
//	}
//
//	public List<Feature> getRequiredFeatures() {
//		return new LinkedList<Feature>();
//	}
//
//	public String getFitnessFunction() {
//		return fitnessFunction_;
//	}
//
//	public void setFitnessFunction(String fitnessFunction) {
//		fitnessFunction_ = fitnessFunction;
//	}
//
//	public boolean shouldMaximizeFitnessFunction() {
//		return maximizeFitnessFunction_;
//	}
//
//	public void setMaximizeFitnessFunction(boolean maximizeFitnessFunction) {
//		maximizeFitnessFunction_ = maximizeFitnessFunction;
//	}
//
//	public List<VariableResolver> getVariableResolvers() {
//		return variableResolvers_;
//	}
//
//	public void setVariableResolvers(List<VariableResolver> variableResolvers) {
//		variableResolvers_ = variableResolvers;
//	}
//
//	/**
//	 * @return the selectionHandler
//	 */
//	public SelectionHandler getSelectionHandler() {
//		return selectionHandler_;
//	}
//
//	/**
//	 * @param selectionHandler
//	 *            the selectionHandler to set
//	 */
//	public void setSelectionHandler(SelectionHandler selectionHandler) {
//		selectionHandler_ = selectionHandler;
//	}
//	
//	public List validTargets(Feature f, List targList){
//		for(Requirement r : f.getRequirements()){
//			targList = validTargets(r, targList);
//		}
//		return targList;
//	}
//	
//	public List validTargets(Requirement req, List targList){
//		if(targList == null || targList.size() < 1)
//			return new ArrayList();
//		
//		ArrayList valid = new ArrayList();
//		for(Object o : targList){
//			if(matches(req, (Node)o)){
//				valid.add(o);
//			}
//		}
//		
//		return valid;
//	}
//	
//	public boolean matches(Requirement r, Node node){
//		for(Resource res : node.getResources()){
//			if(res.getName().equals(r.getTargetProperty())){
//				String value = ""+res.getValue();
//				if("=".equals(r.getRequirementType())){
//					return value.equals(r.getRequiredValue());
//				}
//				else{
//					return true;
//				}
//			}
//		}
//		return false;
//	}

}
